package org.mame.builders;

import java.awt.Desktop;
import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.Properties;
import java.util.TreeMap;
import java.util.Vector;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class BuildMediaReport {
	// Internal variables
	private static Logger log                                = LogManager.getLogger(BuildMediaReport.class.getName());
	private static final String propFileStr                  = "config" + File.separator + "BuildersTest.properties";
	private static String hyperspin_dir                      = "";
	private static String console_name                       = "";
	private static String artwork_folder                     = "";
	private static StringBuffer html                         = new StringBuffer();
	private static String output_dir                         = "";
	private static String output_file_name                   = "";
	private static int cnt                                   = 1;
	private static boolean include_complete_media;
	private static boolean open_report;
	private static File mediaTest;
	private static TreeMap<String, Vector<File>> rom_list;
	
	// Constant variables
	private static final String PROPERTY_HYPERSPIN_DIR       = "hyperspin_base_dir";
	private static final String PROPERTY_CONSOLE_NAME        = "console_name";
	private static final String PROPERTY_ARTWORK_FOLDER      = "artwork_folder";
	private static final String PROPERTY_OUTPUT_DIR          = "output_dir";
	private static final String PROPERTY_OUTPUT_FILE_NAME    = "media_report_file_name";
	private static final String PROPERTY_INCLUDE_COMPLETE    = "includeCompletedROMs";
	private static final String PROPERTY_OPEN_REPORT         = "open_report_on_completion";
	private static final String ARTWORK_EXT                  = ".png";
	private static final String VIDEO_EXT                    = ".flv";
	private static final String CSS_HEADER_STYLE             = "style=\"font-size:20;color:#EFEFFB;background-color:#0000FF;\"";
	private static final String CSS_EVEN_ROW_STYLE           = "style=\"font-size:20;background-color:#A9D0F5;\"";
	private static final String CSS_ODD_ROW_STYLE            = "style=\"font-size:20;background-color:#D8D8D8;\"";
	
	// Error codes
	private static final int ERROR_CONFIGURATION_FILE_ISSUE  = 1;
	private static final int ERROR_PROPERTY_VALUE_REQUIRED   = 2;
	private static final int ERROR_OUTPUT_FILE_FAILURE       = 4;
	
	public static int buildReport(String[] args){
		Properties props = new Properties();
		File propFile;
		
		// Get the property file, either passed in or from the default location
		try {
			if(args != null && args.length > 0){
				propFile = new File(args[0]);
			}else{
				propFile = new File(propFileStr);
			}
			// File must exist to open it, DUH!
			if(!propFile.exists()){
				log.error("Configuration file "+ propFile.getAbsolutePath() + " not found");
				return(ERROR_CONFIGURATION_FILE_ISSUE);
			}
			props.load(new BufferedInputStream(new FileInputStream(propFile)));
			
			log.debug("Properties Output:\n" + props.toString());
			
			// Get properties needed for this class
			hyperspin_dir = props.getProperty(PROPERTY_HYPERSPIN_DIR, "");
			console_name           = props.getProperty(PROPERTY_CONSOLE_NAME, "");
			artwork_folder         = props.getProperty(PROPERTY_ARTWORK_FOLDER, "");
			output_file_name       = props.getProperty(PROPERTY_OUTPUT_FILE_NAME, "");
			output_dir             = props.getProperty(PROPERTY_OUTPUT_DIR, "");
			include_complete_media = new Boolean(props.getProperty(PROPERTY_INCLUDE_COMPLETE, "true")).booleanValue();
			open_report            = new Boolean(props.getProperty(PROPERTY_OPEN_REPORT, "false")).booleanValue();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			System.out.println("Properties file " + propFileStr + " cannot be found");
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		// Null-check required values
		
		
		// Get the list of rom files to check against, borrowed form BuildRomConfigs
		rom_list = BuildRomConfigs.getRomFileList(props);
		
		// Create the media report for this emulator
		buildReport();
		
		outputFile();
		
		return 0;
	}

	private static void outputFile() {
		// TODO Auto-generated method stub
		// Got to have an html file, append .html if it's not already there
			if(!output_file_name.endsWith(".html")){
				log.info("Appending .html to supplied output file name " + output_file_name);
				output_file_name += ".html";
				log.debug("Output file name updated to " + output_file_name);
			}
			
			// Just delete the old file if one existed.  It's useless anyway
			File output = new File(output_dir + File.separator + output_file_name);
			if(output.exists()){
				output.delete();
			}
			try{
				output.createNewFile();
				
				// Throw the XML String out to the newly created file
				FileWriter fw = new FileWriter(output.getAbsoluteFile());
				BufferedWriter bw = new BufferedWriter(fw);
				bw.write(html.toString());
				bw.close();
				
				// If the property is set to open the report then allow the OS to use the default app to do so
				if(open_report){
					Desktop.getDesktop().open(output);
				}
			}catch (IOException ioe){
				log.error("Error creating output file " + output.getAbsolutePath());
				System.exit(ERROR_OUTPUT_FILE_FAILURE);
			}
				
			log.info("Output file " + output.getAbsolutePath() + " written successfully");
	}

	private static void buildReport() {
		// TODO Auto-generated method stub
		createHeaders();
		
		NavigableSet<String> keys = rom_list.navigableKeySet();
		Iterator<String> it = keys.iterator();
		Vector<File> roms;
		File rom;
		
		while(it.hasNext()){
			roms = rom_list.get(it.next());
			for(int i=0; i<roms.size(); i++){
				rom = roms.get(i);
				createTableData(rom);
			}
		}
		
		closeTable();
	}

	private static void closeTable() {
		// TODO Auto-generated method stub
		html.append("\t\t</table>\n\t</body>\n</html>\n");
	}

	private static void createTableData(File rom) {
		// TODO Auto-generated method stub
		String name = rom.getName().substring(0, rom.getName().lastIndexOf("."));
		String console_root = hyperspin_dir + File.separator + "media" + File.separator + console_name;
		boolean hasArtwork = false;
		boolean hasVideo = false;
		
		// File object pointing to where the box/cover/cart artwork will be if it exists
		mediaTest = new File(console_root + File.separator + "Images"
				+ File.separator + artwork_folder + File.separator + name + ARTWORK_EXT);
		log.debug("Searching for box art media, should be " + mediaTest.getAbsolutePath());
		if(mediaTest.exists()){
			hasArtwork = true;
		}
		
		// File object pointing to where the video snaps will be if they exist
		mediaTest = new File(console_root + File.separator + "Video"
				+ File.separator + name + VIDEO_EXT);
		log.debug("Searching for video snaps, should be " + mediaTest.getAbsolutePath());
		if(mediaTest.exists()){
			hasVideo = true;
		}
		
		if(!include_complete_media && hasArtwork && hasVideo){
			log.debug(name + " has all media and is to be excluded from the report");
		}else{
			if(cnt%2 == 0){
				html.append("\t\t\t<tr " + CSS_EVEN_ROW_STYLE + ">\n\t\t\t\t<td>" + name + "</td>\n");
			}else{
				html.append("\t\t\t<tr " + CSS_ODD_ROW_STYLE + ">\n\t\t\t\t<td>" + name + "</td>\n");
			}
			html.append("\t\t\t\t<td>" + hasArtwork + "</td>\n");
			html.append("\t\t\t\t<td>" + hasVideo + "</td>\n\t\t\t</tr>\n");
			cnt++;
		}
	}

	private static void createHeaders() {
		// TODO Auto-generated method stub
		html.append("<html>\n\t<body>\n\t\t<table border=\"1\">\n\t\t\t<tr " + CSS_HEADER_STYLE + ">\n");
		html.append("\t\t\t\t<th>ROM File</th>\n\t\t\t\t<th>Artwork</th>\n");
		html.append("\t\t\t\t<th>Video</th>\n\t\t\t</tr>\n");
	}
}
